/*
 * @Description: CacheUtil
 * @Author: zhaokun
 * @Date: 2022-01-07 15:29:06
 * @LastEditTime: 2022-01-14 17:21:39
 * @FilePath: \user\common\nwCache.go
 */
package common

import (
	"strconv"
	"time"

	"github.com/go-redis/redis"
)

type CacheUtil interface {
	Set(key string, content string, expire int) bool
	Get(key string) string
	Del(key ...string) int64
	Incr(key string) int64
	Decr(key string) int64
	Hkeys(key string) []string
	Hvals(key string) []string
	Hlen(key string) int64
	Hset(key string, field string, value string) bool
	Hget(key string, field string) string
	Lpush(key string, content string) int64
	Rpush(key string, content string) int64
	Lpop(key string) string
	Rpop(key string) string
	Llen(key string) int64
	Lrem(key string, count int64, content string) int64
	Lindex(key string, index int64) string
	Sadd(key string, content ...interface{}) int64
	Scard(key string) int64
	Spop(key string) string
	Sismember(key string, content string) bool
	Smembers(key string) []string
	Subscribe(key ...string) *redis.PubSub
	Publish(key string, content string) int64
	GeoDist(key string, m1 string, m2 string, unit string) float64
	GeoAdd(key string, locations []string) int64
}

type RedisConf struct {
	Addr     string
	Password string
	Db       int
}

type nwCacheUtil struct {
	redisDb *redis.Client
}

func NewNwCacheUtil(conf *RedisConf) *nwCacheUtil {
	nwCache := &nwCacheUtil{}
	nwCache.redisDb = redis.NewClient(&redis.Options{
		Addr:     conf.Addr,
		Password: conf.Password,
		DB:       conf.Db,
	})
	return nwCache
}

func (cache *nwCacheUtil) Set(key string, content string, expire int) bool {
	err := cache.redisDb.Set(key, content, time.Duration(expire)*time.Second).Err()
	if err != nil {
		return false
	}

	return true
}

func (cache *nwCacheUtil) Get(key string) string {
	val, err := cache.redisDb.Get(key).Result()
	if err != nil {
		return ""
	}

	return val
}

func (cache *nwCacheUtil) Del(key ...string) int64 {
	val, err := cache.redisDb.Del(key...).Result()
	if err != nil {
		return 0
	}

	return val
}

func (cache *nwCacheUtil) Incr(key string) int64 {
	val, err := cache.redisDb.Incr(key).Result()
	if err != nil {
		return -1
	}

	return val
}

func (cache *nwCacheUtil) Decr(key string) int64 {
	val, err := cache.redisDb.Decr(key).Result()
	if err != nil {
		return -1
	}

	return val
}

func (cache *nwCacheUtil) Hkeys(key string) []string {
	val, err := cache.redisDb.HKeys(key).Result()
	if err != nil {
		return nil
	}

	return val
}

func (cache *nwCacheUtil) Hvals(key string) []string {
	val, err := cache.redisDb.HVals(key).Result()
	if err != nil {
		return nil
	}

	return val
}

func (cache *nwCacheUtil) Hlen(key string) int64 {
	val, err := cache.redisDb.HLen(key).Result()
	if err != nil {
		return -1
	}

	return val
}

func (cache *nwCacheUtil) Hset(key string, field string, value string) bool {
	val, err := cache.redisDb.HSet(key, field, value).Result()
	if err != nil {
		return false
	}

	return val
}

func (cache *nwCacheUtil) Hget(key string, field string) string {
	val, err := cache.redisDb.HGet(key, field).Result()
	if err != nil {
		return ""
	}

	return val
}

func (cache *nwCacheUtil) Lpush(key string, content string) int64 {
	val, err := cache.redisDb.LPush(key).Result()
	if err != nil {
		return 0
	}

	return val
}

func (cache *nwCacheUtil) Rpush(key string, content string) int64 {
	val, err := cache.redisDb.RPush(key).Result()
	if err != nil {
		return 0
	}

	return val
}

func (cache *nwCacheUtil) Lpop(key string) string {
	val, err := cache.redisDb.LPop(key).Result()
	if err != nil {
		return ""
	}

	return val
}

func (cache *nwCacheUtil) Rpop(key string) string {
	val, err := cache.redisDb.RPop(key).Result()
	if err != nil {
		return ""
	}

	return val
}

func (cache *nwCacheUtil) Llen(key string) int64 {
	val, err := cache.redisDb.LLen(key).Result()
	if err != nil {
		return 0
	}

	return val
}

func (cache *nwCacheUtil) Lrem(key string, count int64, content string) int64 {
	val, err := cache.redisDb.LRem(key, count, content).Result()
	if err != nil {
		return 0
	}

	return val
}

func (cache *nwCacheUtil) Lindex(key string, index int64) string {
	val, err := cache.redisDb.LIndex(key, index).Result()
	if err != nil {
		return ""
	}

	return val
}

func (cache *nwCacheUtil) Sadd(key string, content ...interface{}) int64 {
	val, err := cache.redisDb.SAdd(key, content...).Result()
	if err != nil {
		return 0
	}

	return val
}
func (cache *nwCacheUtil) Scard(key string) int64 {
	val, err := cache.redisDb.SCard(key).Result()
	if err != nil {
		return 0
	}

	return val
}

func (cache *nwCacheUtil) Spop(key string) string {
	val, err := cache.redisDb.SPop(key).Result()
	if err != nil {
		return ""
	}

	return val
}
func (cache *nwCacheUtil) Sismember(key string, content string) bool {
	val, err := cache.redisDb.SIsMember(key, content).Result()
	if err != nil {
		return false
	}

	return val
}
func (cache *nwCacheUtil) Smembers(key string) []string {
	val, err := cache.redisDb.SMembers(key).Result()
	if err != nil {
		return nil
	}

	return val
}
func (cache *nwCacheUtil) Subscribe(key ...string) *redis.PubSub {
	sub := cache.redisDb.Subscribe(key...)

	return sub
}
func (cache *nwCacheUtil) Publish(key string, content string) int64 {
	val, err := cache.redisDb.Publish(key, content).Result()
	if err != nil {
		return 0
	}

	return val
}
func (cache *nwCacheUtil) GeoDist(key string, m1 string, m2 string, unit string) float64 {
	val, err := cache.redisDb.GeoDist(key, m1, m2, unit).Result()
	if err != nil {
		return 0
	}

	return val
}

func (cache *nwCacheUtil) GeoAdd(key string, locations []string) int64 {

	if len(locations) > 0 {
		lat, _ := strconv.ParseFloat(locations[1], 64)
		lng, _ := strconv.ParseFloat(locations[2], 64)
		item := &redis.GeoLocation{
			Name:      locations[0],
			Latitude:  lat,
			Longitude: lng,
		}
		val, err := cache.redisDb.GeoAdd(key, item).Result()
		if err != nil {
			return 0
		}
		return val
	}
	return 0
}
